#ifndef __CHAR_INSTANCE_MANAGER_H__
  #define __CHAR_INSTANCE_MANAGER_H__

#include "char_list.h"

using namespace std;

namespace char_memory_management {

//! Character insatnce manager

/*!
Allocating too many small objects can cause performance problems. That is why this class can
help to reduce the overhead of object creation by allocating arrays of objects.
This means, that we do fewer allocation operations, but each time we allocate enough memory for
many instances.

All allocated instances will be freed when destructing this class.
The destructor is not defined virtual because of efficiency reasons, please do not inherit from
this class.

This class "char_instance_manager" consists of a char_list. A char_list can have many char_node objects.
Every char_node is an array of characters, which can contain many small strings in it.
A null termination character will be added between these small strings.

Implementation date: 2008

Usage:

This class is implemented for internal usage to be used inside database classes. Please do not use
this class for other purposes.
*/

  class char_instance_manager {
  private:
    char_list arrays; // list of allocated arrays
    const unsigned int block_size;

    char_instance_manager &operator=(const char_instance_manager &im); // not allowed
    char_instance_manager(const char_instance_manager &im); // not allowed

  public:
    //! releases all instances & allocated memory
    void release() {
      char_node *tmp = const_cast<char_node*>(arrays.get_head());
      while (tmp != 0) {
        delete[] tmp->get_value();
        tmp = const_cast<char_node*>(tmp->get_next());
      } // while

      arrays.release();
    } // release

    //! returns a character buffer (char*) as large as requested
    char *get_new_instance(unsigned int size) {
      if (size == 0)
        return 0;

      char_node *result = const_cast<char_node*>(arrays.find_the_suitable_node(size));
      if (result != 0)
        return result->allocate(size);
      else {
        const unsigned int max_size = max(size, block_size) + 1;
        char *s1 = new char[max_size]; // will be deleted by char_instance_manager

        result = new char_node(s1, max_size); // will be deleted by list, list takes the ownership of its elements

        char *s2 = result->allocate(size);
        arrays.prepend(result);
        return s2;
      } // else
    } // get_new_instance

    //! constructor: block_size is the default size for each array allocation
    char_instance_manager(unsigned int block_size) : block_size(block_size) {
      // nothing to do
    } // char_instance_manager

    //! destructor (non-virtual: please do not inherit from this class)
    ~char_instance_manager() {
      release();
    } // ~char_instance_manager
  }; // class char_instance_manager

} // namespace char_memory_management

#endif
